package com.hfh.server.netty_server.service;

import com.hfh.server.netty_server.MessageDTO;
import com.hfh.server.netty_server.ServerHandler;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.Collection;
import java.util.List;
/**
 * @author liuxinghong
 * @Description: 服务端向客户端发送消息
 * @date 2019/9/4 000410:52
 */
@Slf4j
@Service
public class NettyServerMessageImpl implements NettyServerMessageService {

    /**
     * 发送给所有的客户端
     * @param message
     */
    @Override
   public  void sendAllClient(MessageDTO message) {
       Collection<Channel> channels = ServerHandler.nettyChannelKey.values();
       if (!CollectionUtils.isEmpty(channels)){
           channels.forEach(channel->{
               ChannelFuture channelFuture = channel.writeAndFlush(message);
               channelFuture.addListener((ChannelFuture futureListener) -> {
                   if (!futureListener.isSuccess()) { //消息发送失败后要处理的事情
                       // todo: 提供两种解决方案 1. 放入redis 定时重试  2. 放入数据库 ，多线程并发重试
                       log.info("消息发送失败，提供两种解决方案 1. 放入redis 定时重试  2. 放入数据库 ，多线程并发重试 ");
                   }else {
                       //todo：
                   }
               });
               if(1!=ServerHandler.clientHeatBeatCountMap.get(channel.id().asShortText())){
                   ServerHandler.clientHeatBeatCountMap.replace(channel.id().asShortText(),1);//当收到客户端发来的任何消息时，设置服务端检测此客户端心跳检测次数为初始值
               }
           });
   }
   }

    /**
     * 向指定客户端发送消息
     * @param keyList 客户端识别id
     * @param message 消息体
     */
    @Override
    public  void sendClientMessage(List<String> keyList,MessageDTO message){
            if (!CollectionUtils.isEmpty(keyList)){
                keyList.forEach(item->{
                    Channel channel = ServerHandler.nettyChannelKey.get(item);
                    if (null == channel){
                        //todo：通道未建立连接或者断开连接 ，此处将发送的消息存放起来，利用定时任务去扫描发送
                        log.info("客户端："+item +"通道未建立连接，发送失败");
                    }
                    ChannelFuture channelFuture = channel.writeAndFlush(message);
                    channelFuture.addListener((ChannelFuture futureListener) -> {
                        if (!futureListener.isSuccess()) { //消息发送失败后要处理的事情
                           // todo: 提供两种解决方案 1. 放入redis 定时重试  2. 放入数据库 ，多线程并发重试
                            log.info("消息发送失败，提供两种解决方案 1. 放入redis 定时重试  2. 放入数据库 ，多线程并发重试 ");
                        }else {
                            //todo：成功要处理的事
                        }
                    });
                    if(1!=ServerHandler.clientHeatBeatCountMap.get(channel.id().asShortText())){
                        ServerHandler.clientHeatBeatCountMap.replace(channel.id().asShortText(),1);//当收到客户端发来的任何消息时，设置服务端检测此客户端心跳检测次数为初始值
                    }
                });
            }
    }

    /**
     * 读取收到的业务逻辑消息
     * 消息类型 1 通知消息 2 对话消息 3 执行指令消息 4 对话回复消息 0 普通消息  -1 首次连接建立客户端和服务器端识别
     * @param message
     */
    @Override
    public  void readMessage(MessageDTO message) {
        //todo： 执行业务逻辑

    }

//    /**
//     * 读取到当前消息后回复客户端信息
//     */
//    Override
//    public  MessageDTO readMessageReply() {
//        //todo： 执行业务逻辑
//        return MessageDTO.builder().senderId(Constants.NETTY_SERVER_ID)
//                .messageBody("已经收到消息")
//                .sendTime(DateTime.now().toString(Constants.YYYY_MM_DD_HH_MM_SS))
//                .type(Constants.NETTY_MESSAGE_REPLY_TYPE)//消息类型为回复消息
//                .build();
//    }
}
